#include <StVenKir.hpp>
#include <iostream>
#include <feel/feelfilters/geotool.hpp>

namespace Feel {

    template<int Dim, int Order, template<uint16_type,uint16_type,uint16_type> class Entity>
    StVenantKirchhoff<Dim,Order,Entity>::StVenantKirchhoff( application_ptrtype __appli )
        :
        M_lifeApplication(__appli),
        M_backend( backend_type::build( this->application()->vm() ) ),
        meshSize( this->application()->vm()["struct-hsize"].template as<double>() ),
        M_mesh_struct(this->createMesh( meshSize )),
        M_Xh(new space_struct_type( M_mesh_struct ) ),
        U_displ_struct( new element_struct_type( M_Xh, "structure displacement" )),
        U_velocity_struct( new element_struct_type( M_Xh, "structure velocity" )),
        U_acceleration_struct( new element_struct_type( M_Xh, "structure acceleration" )),
        M_velocityInterface( new element_struct_type( M_Xh, "velocityInterface" )),
        M_bdf_displ_struct ( new bdf_struct_type( this->application()->vm(),M_Xh,"structure displacement" )),
        M_bdf_velocity_struct ( new bdf_struct_type( this->application()->vm(),M_Xh,"structure velocity" )),
        M_bdf_acceleration_struct ( new bdf_struct_type( this->application()->vm(),M_Xh,"structure acceleration" )),
        M_normalStressBoundary(new element_struct_type( M_Xh, "normal Stress Boundary" )),
        M_exporter( exporter_type::New( /*"gmsh"*/this->application()->vm(), /*this->application()->about().appName()*/"ExportStruct" ) ),
        M_cpt_export(0)
    {
        M_weakCL = this->application()->vm()["weakCL"].template as<bool>();
        penalbc = this->application()->vm()["bccoeff"].template as<value_type>();

        M_time = __appli->vm()["bdf-time-initial"].template as<double>();

        EE = 3*1.0e6;//21*1e5;
        sigma = 0.3;//45;//0.3;//0.28;
        //EE = 0.2;//module young (caoutchou)
        //sigma = 0.5;//coeff de poisson (caoutchou)
        mu = EE/(2*(1+sigma));
        lambda = EE*sigma/((1+sigma)*(1-2*sigma));

        M_rho = this->application()->vm()["struct-rho"].template as<double>();

        M_LookComment = this->application()->vm()["struct-verbose"].template as<bool>();
    }


template<int Dim, int Order, template<uint16_type,uint16_type,uint16_type> class Entity>
typename StVenantKirchhoff<Dim,Order,Entity>::mesh_ptrtype
StVenantKirchhoff<Dim,Order,Entity>::createMesh( double meshSize )
{

    if (M_LookComment) std::cout <<"[StVenantKirchhoff] : createMesh start \n";

    this->changeRepository();

    mesh_ptrtype mesh( new mesh_type );

    //Geometry
#if 0
    GeoTool::Node x1h(0,1);
    GeoTool::Node x2h(6,1.1);
#else
    GeoTool::Node x1h(0,0.5);
    GeoTool::Node x2h(6,0.6);
#endif
    GeoTool::Rectangle Rh( meshSize,"StructureH",x1h,x2h);
    Rh.setMarker(_type="line",_name="Exterieur",_marker3=true);
    Rh.setMarker(_type="line",_name="Interieur"/*"Fixe"*/,_marker1=true);
    Rh.setMarker(_type="line",_name="Fixe",_marker2=true,_marker4=true);
    Rh.setMarker(_type="surface",_name="OmegaStructureH",_marker1=true);

#if 0
    GeoTool::Node x1b(0.0,-0.1);
    GeoTool::Node x2b(6.0, 0.0);
#else
    GeoTool::Node x1b(0.0,-0.6);
    GeoTool::Node x2b(6.0, -0.5);
#endif
    GeoTool::Rectangle Rb( meshSize,"StructureB",x1b,x2b);
    Rb.setMarker(_type="line",_name="Exterieur",_marker1=true);
    Rb.setMarker(_type="line",_name="Interieur",_marker3=true);
    Rb.setMarker(_type="line",_name="Fixe",_marker2=true,_marker4=true);
    Rb.setMarker(_type="surface",_name="OmegaStructureB",_marker1=true);


    std::string name = "struct_stvenant";


    if (M_LookComment) std::cout <<"[StVenantKirchhoff] : createMesh finish\n";

    return (Rh+Rb).createMesh<mesh_type>(name);


} // StVenantKirchhoff::createMesh


    template<int Dim, int Order, template<uint16_type,uint16_type,uint16_type> class Entity>
    boost::shared_ptr<typename StVenantKirchhoff<Dim, Order, Entity>::element_dirichlet_type>
    StVenantKirchhoff<Dim, Order, Entity>::getDirichletElement()
    {
        boost::shared_ptr<element_struct_type> bid (new element_struct_type( M_Xh, "bid"));
        return bid;
    }

    template<int Dim, int Order, template<uint16_type,uint16_type,uint16_type> class Entity>
    void
    StVenantKirchhoff<Dim, Order, Entity>::changeRepository(std::string pathLoc)
    {
#if 0
        this->application()->changeRepository( boost::format( "%1%/Struct/%2%/P%3%/h_%4%/" )
                                               % this->application()->about().appName()
                                               % convex_type::name()
                                               % Order
                                               % this->meshSize
                                               );
#endif
    }


template<int Dim, int Order, template<uint16_type,uint16_type,uint16_type> class Entity>
void
StVenantKirchhoff<Dim, Order, Entity>::exportResults()// element_struct_type& U, element_struct_type& V )
{
    if (M_LookComment) std::cout <<"[StVenantKirchhoff] : export start\n";
    this->changeRepository();

#if 0
    // A ameliore
    auto newmesh = this->createMesh( meshSize );
    M_mesh_mover.apply(newmesh, *this->getSolution() );

    auto newspace = space_struct_type::New( newmesh );
    element_struct_type newdispl( newspace, "new structure displacement" );
    element_struct_type newvel( newspace, "new structure velocity" );
    element_struct_type newacc( newspace, "new structure acceleration" );
    element_struct_type newstresstensor( newspace, "new stress tensor" );

    newdispl.container() = U_displ_struct->container();
    newvel.container() = U_velocity_struct->container();
    newacc.container() = U_acceleration_struct->container();
    newstresstensor.container() =  M_normalStressBoundary->container();

    M_exporter->step( M_cpt_export )->setMesh( newmesh );
    M_exporter->step( M_cpt_export )->add( "displ", newdispl );
    M_exporter->step( M_cpt_export )->add( "velocity", newvel );
    M_exporter->step( M_cpt_export )->add( "acceleration", newacc );
    M_exporter->step( M_cpt_export )->add( "stresstensor", newstresstensor );
    M_exporter->save();


#else
    M_exporter->step( M_cpt_export )->setMesh( M_mesh_struct );
    M_exporter->step( M_cpt_export )->add( "displ", *U_displ_struct );
    M_exporter->step( M_cpt_export )->add( "velocity", *U_velocity_struct );
    M_exporter->step( M_cpt_export )->add( "acceleration", *U_acceleration_struct );
    M_exporter->step( M_cpt_export )->add( "stresstensor", *M_normalStressBoundary );
    M_exporter->step( M_cpt_export )->add( "velocityInterface", *M_velocityInterface );
    M_exporter->save();
#endif

    ++M_cpt_export;

    if (M_LookComment) std::cout <<"[StVenantKirchhoff] : export finish\n";

} // StVenantKirchhoff::export


} // Feel

// instantiation
template class Feel::StVenantKirchhoff<2,2,Feel::Simplex>;
//template class Feel::StVenantKirchhoff<3,2,Feel::Simplex>;

